﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Net.Http;
using System.Threading;
using Common.Logging;
using In.Api.Dto.HisWs;
using In.Api.Dto.YBWs;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using User.Api.BizExtensions;
using User.Api.Helpers;
using User.Api.HttpClients;

namespace Out.TaskRunner.RmqWorkers
{
    public class OrderPickupingWorker : IWorker
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(OrderPickupingWorker));

        public void Start(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            using (var consumer = new OrderPickupingConsumer())
            {
                consumer.Subscribe((id, count, dt, msg, channel) =>
                {
                    if (msg.OrderType == OrderType.挂号订单)
                    {
                        return ProcessRegOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.门诊缴费订单)
                    {
                        return ProcessBillOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.住院预缴金订单)
                    {
                        return ProcessInpatientPrepayOrder(msg.OrderId, channel);
                    }

                    return new ConsumedResult { Ack = true };
                });

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }

                    Thread.Sleep(50);
                }
            }
        }

        private ConsumedResult ProcessRegOrder(int orderId, WrapperChannel channel)
        {
            OrderSummary order;
            using (var ctx = new GdsfybjyWeiXinEntities())
            {
                order = ctx.ApptOrders.Where(x => x.Id == orderId)
                    .Select(x => new OrderSummary
                    {
                        Id = x.Id,
                        OrderType = x.OrderType,
                        CardType = x.CardType,
                        CardNo = x.CardNo,
                        OrderStatus = x.OrderStatus,
                        OrderNo = x.OrderNo,
                        SumFee = x.SumFee,
                        WxTransactionId = x.WxTransactionId,
                        PayTime = x.PayTime,
                        DeptId = x.DeptId,
                        RegDate = x.RegDate,
                        TimeSlice = x.TimeSlice,
                        RegType = x.RegType,
                        TreatFee = x.TreatFee,
                        Fee = x.Fee,
                        RegNo = x.RegNo,
                        SqNo = x.Sqno,
                        StartTime = x.StartTime,
                        EndTime = x.EndTime,
                        OtherFee = x.OtherFee,
                        DoctorId = x.DoctorId,
                        BookingNo = x.BookingNo,
                        SvobjectId = x.SvObjectId,
                        InfoSeq = x.InfoSeq
                    }).FirstOrDefault();
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
            }

            var registerRequest = new ExeRegisterRequest();
            registerRequest.RegFlag = order.OrderType;
            registerRequest.RegDate = order.RegDate;
            registerRequest.PayType = "2";
            registerRequest.StartTime = order.StartTime;
            registerRequest.OrderId = order.OrderNo;
            registerRequest.CardNo = order.CardNo;
            registerRequest.PayCount = order.SumFee.ToString();
            registerRequest.TransNo = order.WxTransactionId;
            registerRequest.TransTime = order.PayTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss");
            registerRequest.SourceCode = order.SqNo;
            registerRequest.CardType = order.CardType;
            registerRequest.Sqno = order.RegNo;

            ExeRegisterResponse regResponse;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisSp/ExeRegister", registerRequest).Result;
                responseMsg.EnsureSuccessStatusCode();
                regResponse = responseMsg.Content.ReadAsAsync<ExeRegisterResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内预约Api出错,信息：{0}", JsonConvert.SerializeObject(ex));

                // RMQ 执行取号结果查询
                var pickupingChkProducer = new OrderPickupingChkProducer();
                pickupingChkProducer.Publish(new OrderPickupingChkMsg
                {
                    OrderType = Rmq.Center.OrderType.挂号订单,
                    OrderId = order.Id
                });

                return new ConsumedResult
                {
                    Ack = true
                };
            }
            if (regResponse.ResultCode != "0")
            {
                // 取号失败
                //order.OrderStatus = ApptOrderExtensions.OrderStatus.取号失败.ToInt32();
                //ctx.SaveChanges();
                DataBaseCommandFactory.CreateDatbaseCommand()
                    .UpdateOrderStatus(orderId, ApptOrderExtensions.OrderStatus.取号失败.ToInt32());

                // RMQ 取消预约 
                var unapptingProducer = new OrderUnapptingProducer();
                unapptingProducer.Publish(new OrderUnapptingMsg
                {
                    OrderType = Rmq.Center.OrderType.挂号订单,
                    OrderId = order.Id,
                    Reason = 2
                });

                // RMQ 发送用户挂号失败通知
                var msgProducer = new UserMessageProducer();
                msgProducer.Publish(new UserMessageMsg
                {
                    Type = UserMessageType.挂号失败通知,
                    OrderId = order.Id
                });
                
                // RMQ 执行退费操作
                if (order.SumFee > 0)
                {
                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                    {
                        OrderType = OrderType.挂号订单,
                        OrderId = order.Id
                    });
                }
            }
            else
            {
                DataBaseCommandFactory.CreateDatbaseCommand()
                .PickupSuccess(orderId, regResponse.RegNo, regResponse.BeginTime,
                    regResponse.EndTime, regResponse.Address, regResponse.VisitNo);

                // RMQ 发送用户挂号成功通知
                var messageProducer = new UserMessageProducer();
                messageProducer.Publish(new UserMessageMsg
                {
                    Type = UserMessageType.挂号成功通知,
                    OrderId = order.Id
                });

                // RMQ 发送发货通知
                if (order.SumFee > 0)
                {
                    //TenpayV2Helper.DoDeliverNotify(order.OpenId, order.WxTransactionId,
                    //    "AP" + order.OrderNo, "1", "");
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }


        private ConsumedResult ProcessBillOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new GdsfybjyWeiXinEntities())
            {
                var order = ctx.BillOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 缴费中
                order.OrderStatus = BillOrderExtensions.OrderStatus.缴费中.ToInt32();
                ctx.SaveChanges();


                // 自费缴费
                var personPayRequest = new ExePrescriptionPayRequest();
                personPayRequest.CardNo = order.CardNo;
                personPayRequest.PrescNo = order.ClinicNo;
                personPayRequest.SumFee = order.PrescMoney.ToString();
                personPayRequest.TransNo = order.WxTransactionId;
                personPayRequest.PayWay = "1";
                personPayRequest.TransTime = order.PayTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss");

                ExePrescriptionPayResponse personPayResponse;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisSp/ExePrescriptionPay", personPayRequest).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    personPayResponse = responseMsg.Content.ReadAsAsync<ExePrescriptionPayResponse>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内缴费Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    // RMQ 执行缴费状态结果查询
                    var pickupingChkProducer = new OrderPickupingChkProducer();
                    pickupingChkProducer.Publish(new OrderPickupingChkMsg
                    {
                        OrderType = Rmq.Center.OrderType.门诊缴费订单,
                        OrderId = order.Id
                    });

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                if (personPayResponse.ResultCode != "0")
                {
                    // 缴费失败
                    order.OrderStatus = BillOrderExtensions.OrderStatus.缴费失败.ToInt32();
                    ctx.SaveChanges();

                    // RMQ 发起缴费失败通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.缴费失败通知
                    });

                    // RMQ 发起退款
                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                    {
                        OrderType = OrderType.门诊缴费订单,
                        OrderId = order.Id
                    });

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                else
                {
                    // 缴费成功
                    order.OrderStatus = BillOrderExtensions.OrderStatus.缴费成功.ToInt32();

                    var newBillOrderDisWin = new BillOrderDisWin
                    {
                        BillOrderId = order.Id,
                        DisWin = "",
                        DisWinAdd = personPayResponse.PharmacyPosition,
                        RcptNo = personPayResponse.RcptNo,
                        VisitNo = ""
                    };
                    ctx.BillOrderDisWins.Add(newBillOrderDisWin);
                    ctx.SaveChanges();

                    // RMQ 发起缴费成功通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.缴费成功通知
                    });

                    // RMQ 发送发货通知
                    //TenpayV2Helper.DoDeliverNotify(order.OpenId, order.WxTransactionId,
                    //        "BL" + order.OrderNo, "1", "");
                }
            }


            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessInpatientPrepayOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new GdsfybjyWeiXinEntities())
            {
                var order = ctx.InpatientPrepayOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                var patient = ctx.HospCards.FirstOrDefault(x => x.CardNo == order.CardNo);
                order.CardName = patient?.PatientName;
                // 缴费中
                order.OrderStatus = PrepayOrderExtensions.OrderStatus.缴费中.ToInt32();
                ctx.SaveChanges();

                var request = new IcCardTranToPrepayRequest();
                //request.OrderId = order.OrderNo;
                request.CardNo = order.CardNo;
                request.PayType = "2";
                request.TransNo = order.WxTransactionId;
                request.TransTime = order.PayTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss");
                request.Zje = order.PrepayMoney.ToString();

                IcCardTranToPrepayResponse response;
                try
                {
                    var httpClient = InHttpClient.GetClient();
                    var responseMsg = httpClient.PostAsJsonAsync("HisSp/IcCardTranToPrepay", request).Result;
                    responseMsg.EnsureSuccessStatusCode();
                    response = responseMsg.Content.ReadAsAsync<IcCardTranToPrepayResponse>().Result;
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用院内缴纳预缴金Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    // RMQ 执行缴费状态结果查询
                    var pickupingChkProducer = new OrderPickupingChkProducer();
                    pickupingChkProducer.Publish(new OrderPickupingChkMsg
                    {
                        OrderType = Rmq.Center.OrderType.住院预缴金订单,
                        OrderId = order.Id
                    });

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                if (response.ResultCode != "0")
                {
                    // 缴费失败
                    order.OrderStatus = PrepayOrderExtensions.OrderStatus.缴费失败.ToInt32();
                    ctx.SaveChanges();

                    // RMQ 发起住院预缴金失败通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.住院预缴金失败通知
                    });

                    // RMQ 发起退款
                    var refundingProducer = new OrderRefundingPickupFailedProducer();
                    refundingProducer.Publish(new OrderRefundingPickupFailedMsg
                    {
                        OrderType = OrderType.住院预缴金订单,
                        OrderId = order.Id
                    });

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                else
                {
                    // 缴费成功
                    order.OrderStatus = PrepayOrderExtensions.OrderStatus.缴费成功.ToInt32();
                    ctx.SaveChanges();
                    // RMQ 发起住院预缴金成功通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.住院预缴金成功通知
                    });


                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }


    }

    public class OrderSummary
    {
        public string OrderNo { get; set; }
        public string OrderType { get; set; }
        public int Id { get; set; }
        public decimal? SumFee { get; set; }
        public string WxTransactionId { get; set; }
        public DateTime? PayTime { get; set; }
        public string CardNo { get; set; }
        public int OrderStatus { get; set; }

        public string DeptId { get; set; }
        public string RegDate { get; set; }
        public string TimeSlice { get; set; }
        public string RegType { get; set; }
        public decimal? TreatFee { get; set; }
        public decimal? Fee { get; set; }
        public string RegNo { get; set; }
        public string StartTime { get; set; }
        public string EndTime { get; set; }
        public decimal? OtherFee { get; set; }
        public string DoctorId { get; set; }

        public string BookingNo { get; set; }

        public string SvobjectId { get; set; }

        public string LockId { get; set; }

        public string InfoSeq { get; set; }
        public string SqNo { get; internal set; }
        public string CardType { get; internal set; }
    }
}